<Project>
  <PropertyGroup>
    <IlcToolsPath>$(CoreCLRILCompilerDir)</IlcToolsPath>
    <IlcToolsPath Condition="'$(TargetArchitecture)' != '$(BuildArchitecture)' or '$(EnableNativeSanitizers)' != ''">$(CoreCLRCrossILCompilerDir)</IlcToolsPath>
  </PropertyGroup>

  <ItemGroup>
    <TestConsoleAppSourceFiles Condition="'@(TestConsoleAppSourceFiles)' == ''" Include="$(MSBuildProjectDirectory)\*.cs" />

    <TestSupportFiles Include="$(MSBuildThisFileDirectory)SupportFiles\Directory.Build.*">
      <DestinationFolder>$(TrimmingTestDir)</DestinationFolder>
    </TestSupportFiles>
  </ItemGroup>

  <Target Name="CreateTestDir"
          Inputs="@(TestSupportFiles)"
          Outputs="@(TestSupportFiles->'%(DestinationFolder)\%(FileName)%(Extension)')">
    <MakeDir Directories="%(TestSupportFiles.DestinationFolder)" />
    <Copy SourceFiles="@(TestSupportFiles)" DestinationFolder="%(TestSupportFiles.DestinationFolder)" />
  </Target>

  <Target Name="GetTestConsoleApps">
    <ItemGroup>
      <TestConsoleAppSourceFiles>
        <ProjectDir>$([MSBuild]::NormalizeDirectory('$(TrimmingTestProjectsDir)', '$(MSBuildProjectName)', '%(Filename)', '$(PackageRID)'))</ProjectDir>
        <TestRuntimeIdentifier>$(PackageRID)</TestRuntimeIdentifier>
        <TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
        <TargetFramework Condition="'%(TestConsoleAppSourceFiles.TargetOS)' != ''">$(NetCoreAppCurrent)-%(TestConsoleAppSourceFiles.TargetOS)</TargetFramework>
      </TestConsoleAppSourceFiles>
      <!-- We need to separate Item metadata declaration in two in order to be able to use ProjectDir and TestRuntimeIdentifier below -->
      <TestConsoleAppSourceFiles>
        <ProjectFile>%(ProjectDir)project.csproj</ProjectFile>
        <TestCommand Condition="'$(TargetArchitecture)' != 'wasm' or '$(TargetOS)' != 'browser'">$([MSBuild]::NormalizePath('%(ProjectDir)', 'bin', '$(Configuration)', '%(TargetFramework)', '%(TestRuntimeIdentifier)', 'publish', 'project'))</TestCommand>
        <TestCommand Condition="'$(TargetArchitecture)' == 'wasm' and '$(TargetOS)' == 'browser'">$([MSBuild]::NormalizePath('%(ProjectDir)', 'bin', '$(Configuration)', '%(TargetFramework)', '%(TestRuntimeIdentifier)', 'AppBundle', 'run-v8.sh'))</TestCommand>
        <TestExecutionDirectory Condition="'$(TargetArchitecture)' != 'wasm' or '$(TargetOS)' != 'browser'">$([MSBuild]::NormalizeDirectory('%(ProjectDir)', 'bin', '$(Configuration)', '%(TargetFramework)', '%(TestRuntimeIdentifier)', 'publish'))</TestExecutionDirectory>
        <TestExecutionDirectory Condition="'$(TargetArchitecture)' == 'wasm' and '$(TargetOS)' == 'browser'">$([MSBuild]::NormalizeDirectory('%(ProjectDir)', 'bin', '$(Configuration)', '%(TargetFramework)', '%(TestRuntimeIdentifier)', 'AppBundle'))</TestExecutionDirectory>
      </TestConsoleAppSourceFiles>
    </ItemGroup>

    <ItemGroup Condition="!$(SkipOnTestRuntimes.Contains('$(PackageRID)'))">
      <TestConsoleApps Include="@(TestConsoleAppSourceFiles->'%(ProjectFile)')" Condition="!$([System.String]::Copy('%(TestConsoleAppSourceFiles.SkipOnTestRuntimes)').Contains('$(PackageRID)'))">
        <ProjectCompileItems>%(FullPath)</ProjectCompileItems>
      </TestConsoleApps>
      <TestConsoleApps AdditionalProperties="MSBuildEnableWorkloadResolver=$(MSBuildEnableWorkloadResolver)" Condition="'$(MSBuildEnableWorkloadResolver)' != ''" />
    </ItemGroup>
  </Target>

  <Target Name="GenerateProjects"
          DependsOnTargets="GetTestConsoleApps;CreateTestDir"
          Inputs="@(TestConsoleAppSourceFiles);$(ProjectTemplate);@(TestSupportFiles)"
          Outputs="%(TestConsoleApps.Identity)">
    <PropertyGroup>
      <_projectDir>%(TestConsoleApps.ProjectDir)\</_projectDir>
      <_projectFile>%(TestConsoleApps.ProjectFile)</_projectFile>
      <_projectSourceFile>%(TestConsoleApps.ProjectCompileItems)</_projectSourceFile>
    </PropertyGroup>

    <ItemGroup Condition="'$(AdditionalProjectReferences)' != ''">
      <_additionalProjectReferenceTemp Include="$(AdditionalProjectReferences)" />
      <_additionalProjectReference Include="&lt;ProjectReference Include=&quot;$(LibrariesProjectRoot)%(_additionalProjectReferenceTemp.Identity)\src\%(_additionalProjectReferenceTemp.Identity).csproj&quot; SkipUseReferenceAssembly=&quot;true&quot; /&gt;" />
    </ItemGroup>

    <PropertyGroup>
      <_additionalProjectReferencesString>@(_additionalProjectReference, '%0a')</_additionalProjectReferencesString>
    </PropertyGroup>

    <ItemGroup>
      <_additionalProjectSourceFiles Include="%(TestConsoleApps.AdditionalSourceFiles)" />
    </ItemGroup>

    <ItemGroup>
      <_switchesAsItems Include="%(TestConsoleApps.DisabledFeatureSwitches)" Value="false" />
      <_switchesAsItems Include="%(TestConsoleApps.EnabledFeatureSwitches)" Value="true" />

      <_propertiesAsItems Include="%(TestConsoleApps.DisabledProperties)" Value="false" />
      <_propertiesAsItems Include="%(TestConsoleApps.EnabledProperties)" Value="true" />
    </ItemGroup>

    <PropertyGroup>
      <_runtimeHostConfigurationOptionsString>@(_switchesAsItems->'&lt;RuntimeHostConfigurationOption Include=&quot;%(Identity)&quot; Value=&quot;%(Value)&quot; Trim=&quot;true&quot; /&gt;', '%0a    ')</_runtimeHostConfigurationOptionsString>
      <_additionalPropertiesString>@(_propertiesAsItems->'&lt;%(Identity)&gt;%(Value)&lt;/%(Identity)&gt;', '%0a    ')</_additionalPropertiesString>
    </PropertyGroup>

    <MakeDir Directories="$(_projectDir)" />
    <WriteLinesToFile File="$(_projectFile)"
                      Lines="$([System.IO.File]::ReadAllText('$(ProjectTemplate)')
                                                 .Replace('{TargetFramework}', '%(TestConsoleApps.TargetFramework)')
                                                 .Replace('{NetCoreAppMaximumVersion}', '$(NetCoreAppMaximumVersion)')
                                                 .Replace('{UseMonoRuntime}','$(UseMonoRuntime)')
                                                 .Replace('{RuntimeIdentifier}','%(TestConsoleApps.TestRuntimeIdentifier)')
                                                 .Replace('{PublishAot}','$(IsNativeAotTestProject)')
                                                 .Replace('{ExtraTrimmerArgs}', '%(TestConsoleApps.ExtraTrimmerArgs)')
                                                 .Replace('{AdditionalProperties}', '$(_additionalPropertiesString)')
                                                 .Replace('{ToolsILLinkDir}', '$(ToolsILLinkDir)')
                                                 .Replace('{IlcToolsPath}', '$(IlcToolsPath)')
                                                 .Replace('{IlcBuildTasksPath}', '$(CoreCLRILCompilerDir)netstandard/ILCompiler.Build.Tasks.dll')
                                                 .Replace('{IlcSdkPath}', '$(CoreCLRAotSdkDir)')
                                                 .Replace('{IlcFrameworkPath}', '$(MicrosoftNetCoreAppRuntimePackRidLibTfmDir)')
                                                 .Replace('{IlcFrameworkNativePath}', '$(MicrosoftNetCoreAppRuntimePackNativeDir)')
                                                 .Replace('{CoreCLRBuildIntegrationDir}', '$(CoreCLRBuildIntegrationDir)')
                                                 .Replace('{RuntimeHostConfigurationOptions}', '$(_runtimeHostConfigurationOptionsString)')
                                                 .Replace('{AdditionalProjectReferences}', '$(_additionalProjectReferencesString)')
                                                 .Replace('{RepositoryEngineeringDir}', '$(RepositoryEngineeringDir)')
                                                 .Replace('{MonoAOTCompilerDir}', '$(MonoAOTCompilerDir)')
                                                 .Replace('{MonoProjectRoot}', '$(MonoProjectRoot)')
                                                 .Replace('{BrowserProjectRoot}', '$(BrowserProjectRoot)')
                                                 .Replace('{WasmProjectRoot}', '$(WasmProjectRoot)')
                                                 .Replace('{WasiProjectRoot}', '$(WasiProjectRoot)')
                                                 .Replace('{MonoAOTCompilerTasksAssemblyPath}', '$(MonoAOTCompilerTasksAssemblyPath)')
                                                 .Replace('{MonoTargetsTasksAssemblyPath}', '$(MonoTargetsTasksAssemblyPath)')
                                                 .Replace('{WasmAppBuilderTasksAssemblyPath}', '$(WasmAppBuilderTasksAssemblyPath)')
                                                 .Replace('{MicrosoftNetCoreAppRuntimePackRidDir}', '$(MicrosoftNetCoreAppRuntimePackRidDir)')
                                                 .Replace('{ProductVersion}', '$(ProductVersion)')
                                                 .Replace('{NetCoreAppCurrent}', '$(NetCoreAppCurrent)')
                                                 .Replace('{NetCoreAppToolCurrent}', '$(NetCoreAppToolCurrent)')
                                                 .Replace('{NetCoreAppCurrentVersion}', '$(NetCoreAppCurrentVersion)')
                                                 .Replace('{MicrosoftNetCoreAppFrameworkName}', '$(MicrosoftNetCoreAppFrameworkName)')
                                                 .Replace('{MicrosoftNetCoreAppRefPackDir}', '$(MicrosoftNetCoreAppRefPackDir)')
                                                 .Replace('{MicrosoftNetCoreAppRuntimePackDir}', '$(MicrosoftNetCoreAppRuntimePackDir)')
                                                 .Replace('{NativeSanitizersTargets}', '$(RepositoryEngineeringDir)nativeSanitizers.targets')
                                                 .Replace('{AppHostSourcePath}', '$(AppHostSourcePath)')
                                                 .Replace('{SingleFileHostSourcePath}', '$(SingleFileHostSourcePath)')
                                                 .Replace('{SanitizerRuntimeFolder}', '$(DotNetHostBinDir)'))"
                      Overwrite="true" />
    <Copy SourceFiles="$(_projectSourceFile);
                       @(_additionalProjectSourceFiles)"
          DestinationFolder="$(_projectDir)" />
    <Message Text="Generated $(_projectFile)" />
  </Target>

  <Target Name="GetTrimmingProjectsToRestore"
          DependsOnTargets="GenerateProjects"
          Returns="@(TestConsoleApps)" />

  <Target Name="PublishTrimmedProjects"
          DependsOnTargets="GenerateProjects">

    <MSBuild Projects="@(TestConsoleApps)"
             Targets="Restore"
             Condition="'$(SkipTrimmingProjectsRestore)' != 'true'"
             Properties="MSBuildRestoreSessionId=$([System.Guid]::NewGuid());Configuration=$(Configuration)" />

    <MSBuild Projects="@(TestConsoleApps)"
             Targets="Publish"
             Properties="Configuration=$(Configuration);BuildProjectReferences=false;TargetOS=$(TargetOS);TargetArchitecture=$(TargetArchitecture)" />
  </Target>

  <Target Name="ExecuteApplications"
          DependsOnTargets="PublishTrimmedProjects"
          Inputs="%(TestConsoleApps.Identity)"
          Outputs="_unused"
          Condition="'$(ArchiveTests)' != 'true'">

    <Message Importance="High" Text="[Trimming Tests] Running test: %(TestConsoleApps.ProjectCompileItems) ..." />
    <Exec IgnoreExitCode="true" Command="%(TestConsoleApps.TestCommand)" StandardOutputImportance="Low" WorkingDirectory="%(TestConsoleApps.TestExecutionDirectory)">
      <Output TaskParameter="ExitCode" PropertyName="ExecutionExitCode" />
    </Exec>

    <Error Condition="'$(ExecutionExitCode)' != '100'" Text="Error: [Failed Test]: %(TestConsoleApps.ProjectCompileItems). The Command %(TestConsoleApps.TestCommand) return a non-success exit code." ContinueOnError="ErrorAndContinue" />
  </Target>

  <Target Name="Build" DependsOnTargets="ExecuteApplications" />

  <!-- define test to do nothing, for this project Build does all the testing -->
  <Target Name="Test" DependsOnTargets="Build" />
  <Target Name="VSTest" DependsOnTargets="Build" />
</Project>
